;:sys36864
	;.opt oo
	*=$ce49
; ---
; uncrash - absturz-versicherung
; nikolaus heusler  5.92
; nach robert masters, 7.87
; ---
; **** konstanten-definitionen
clrchn	=$ffcc	;dateien schliessen
direct	=$302	;direktmodus-vektor
ready	=$a474	;ready-einsprung
link	=$a533	;programm neu binden
clr	=$a660	;clr - befehl
strout	=$ab1e	;text ausgeben
poke	=$b828	;poke-befehl
basicinit	=$e453	;basic einrichten
chkkey	=$f6bc	;tastendruck pruefen
hwinit	=$fd15	;hardware einrichten
irqinit	=$fda3	;interrupts einrichten
nmi	=$fe56	;nmi-einsprung
rsres	=$fe66	;rs232 reset
nonmi	=$fe72	;nmi beenden
gores	=$fffc	;hardware-reset-vektor
goirq	=$fffe	;hardware-irq-vektor
endram	=$283	;hoechste speicherpostion
crsr	=$286	;cursorfarbe
kbvec	=$28f	;zeiger auf tastaturauswertung
cia2x	=$2a1	;rs232 steuerung
dbrk	=$316	;brk-vektor
dnmi	=$318	;nmi-vektor
schmal	=$d016	;bildschirmrand verbreitern
col1	=$d020	;bildschirmrahmenfarbe
col2	=$d021	;hintergrundfarbe
cia2y	=$dd0d	;rs232 steuerung
nmivec	=$fffa	;hardware-nmi-vektor
port	=1	;prozessorport
ioin	=$13	;i/o
tmp	=$22	;zwischenspeicher
memend	=$31	;zeiger auf speicherende
stop	=$91	;run/stop taste
; **** sprungtabelle
	jmp run1	;neu installieren
	jmp run2	;einblenden
; **** uncrash installieren
run1	jsr install
	bit flag	;basic-programm vorhanden
	bpl fg0	;nein, dann fertig
	jmp repair	;programm zurueckholen
; **** uncrash einblenden
run2	jsr unnew	;basicprogramm zurueckholen
	lda tmp
	clc
	adc #2
	sta 45	;programmendezeiger
	lda tmp+1	;neu berechnen
	adc #0
	sta 46
	jsr clr	;pointer rueckstellen
	jmp ready	;und fertig
; **** kein programm im speicher
fg0	lda cia2x
	sta cia2y	;rs232 steuerung
	rts	;fertig
; **** uncrash einrichten
install	jsr farben	;farben setzen
	lda #<hi
	ldy #>hi
	jsr strout	;meldung ausgeben
act	ldy #6	;neue poke-routine anlegen
l2	lda hardpoke,y
	sta poke,y	;in ram unter rom schreiben
	dey	;sieben bytes
	bpl l2
	lda #$7f
	sta cia2y	;rs232 steuerung
	ldy #5
l3	lda hwvec,y	;neue hardware-vektoren einrichten
	sta nmivec,y	;ins ram kopieren
	dey	;sechs bytes
	bpl l3
	ldy #3
l4	lda brktab,y	;neue basic-vektoren
	sta dbrk,y	;einrichten
	dey	;vier bytes
	bpl l4
	rts
; **** abbruch von nmi
qrti	rti
; **** neuer nmi-vektor
hwnmi	sei	;irq sperren
	pha	;akku merken
	txa
	pha	;x-reg. merken
	tya
	pha	;y-reg. merken
	lda #55
	sta port	;rom einschalten
	lda #$7f
	sta cia2y	;auf rs232 testen
	ldy cia2y
	bpl oknmi	;kein rs232, dann ok
	jmp nonmi	;bei rs232 nmi abbrechen
; **** nmi-handler
oknmi	jsr setnmiv	;vektoren neu setzen
	lda #-1
	jsr pause	;kurze pause
	jsr init	;zeiger einrichten
	jsr chkkey	;auf taste pruefen
	lda stop	;tasten (1,2,_) gedrueckt
	cmp #$f4	;testen
	beq hwres	;ja, dann hardware-reset
	cmp #$7f	;runstop gedrueckt
	bne nodir	;nein, dann abbruch
	jsr setdir	;direktmodus-zeiger setzen
nodir	jmp nmi	;nmi fortsetzen
; **** zeiger einrichten
init	jsr setnmiv	;nmi vektor setzen
	jsr clrchn	;i/o-kanaele schliessen
	lda #0
	sta ioin	;eingabegeraet tastatur
	lda #$48
	sta kbvec	;tastaturvektor auf
	lda #$eb	;$eb48 (normalwert)
	sta kbvec+1
	jsr basicinit	;basic einrichten
	jsr hwinit	;hardware einrichten
	jsr act	;uncrash einrichten
	jmp irqinit	;interrupts einrichten
; direktmodus-zeiger zurueckholen
setdir	lda dirmerk
	sta direct
	lda dirmerk+1
	sta direct+1
	rts
; neuer vektor fuer direktmodus
dirmod	jsr farben	;bildschirmfarben setzen
	jsr act	;uncrash einrichten
	lda #$83
	sta direct	;direktmodus-vektor auf
	lda #$a4	;$a483 (normalwert)
	sta direct+1
	jmp (direct)	;und sprung nach $a483
; neuer break-einsprung
break	jsr init	;zeiger einrichten
	jsr setdir	;direktmodus-zeiger korrigieren
	jmp rsres	;und weiter wie gehabt
; neuer irq-einsprung
hwirq	pha	;akku retten
	lda #55	;rom einschalten
	sta port
	pla	;akku zurueckholen
	jmp (goirq)	;weiter im interrupt
; nmi-vektor setzen
setnmiv	lda #55
	sta port	;rom einschalten
	lda #$7f
	sta cia2y	;rs232 steuerung
	lda nmimerk	;alten nmi-vektor
	sta dnmi	;wiederherstellen
	lda nmimerk+1
	sta dnmi+1
	rts	;und fertig
; **** hardware initialisieren
hwres	jsr setnmiv	;nmi-vektor setzen
	sec
	ror flag	;flag basic-programm im speicher
	ldy #13
l6	lda 43,y	;basic-pointer merken
	sta store,y	;dazu zwischenspeichern
	dey	;14 bytes
	bpl l6
	lda endram	;endezeiger
	sta ramend	;retten
	lda endram+1	;auch highbyte
	sta ramend+1
	lda #5	;bildschirmrahmen erweitern
	sta schmal
	lda #$a0	;lange pause
	jsr pause
	jmp (gores)	;weiter in reset-routine
; **** bildschirmfarben setzen
farben	lda #11	;dunkelgrau
	sta crsr	;als cursorfarbe
	lda #12	;mittelgrau
	sta col1	;als bildschirmrahmen
	lda #15	;hellgrau
	sta col2	;fuer den hintergrund
noprg	rts	;fertig
; **** basic-programm reparieren
repair	lsr flag	;flag loeschen
	lda memend	;programm im speicher
	cmp #3	;lowbyte von $803 (wert nach new)
	bne noprg	;nein, dann kein programm
	lda memend+1
	cmp #8	;highbyte von $803
	bne noprg	;abweichung, dann kein programm
	ldy #13	;14 bytes
l1	lda store,y	;zurueckholen
	sta 43,y	;(wurde gesichert, vgl. oben)
	dey	;14 bytes
	bpl l1
	lda ramend	;pointer zurueckholen
	sta endram
	lda ramend+1
	sta endram+1
	sec
	lda 45
	sbc 43
	cmp #2	;programmlaenge kleiner 2
	bne unnew	;dann kein programm im speicher
	lda 46
	sbc 44
	beq noprg
unnew	lda #1	;renew
	tay	;geloeschtes programm zurueckholen
	sta (43),y	;linkpointer schalten
	jmp link	;basiczeilen neu binden
; **** neue poke-routine
hardpoke	ldx #55
	stx port	;rom einschalten
	jmp poke	;weiter mit normalem poke
; **** warteschleife
pause	ldy #0
	ldx #$fc	;entspricht ca. 1 ms
wait2	sta temp
wait	iny	;warteschleife
	bne wait
	inc temp
	bne wait
	inx
	bne wait2
	rts	;genug gewartet
; **** bereich fuer tabellen und texte
hi	.byt 13
	.byte "uncrash"
	.byt 13,0	;einschaltmeldung im ascii-code
flag	brk	;flag basicprogramm
temp	brk	;zwischenspeicher
store	.word 0,0,0,0,0,0	;speicher fuer basic-zeiger
ramend	.word 0	;merker fuer speicherende
hwvec	.word hwnmi,hwres,hwirq	;neue hardware-vektoren
brktab	.word break,hwnmi	;neue systemvektoren
nmimerk	.word qrti	;merker fuer nmi-vektor
dirmerk	.word dirmod	;merker fuer direktmodus-vektor
; ende
